/**
 * @brief tcpServer模块的封装
 * @details
 * 1.成员变量中有由应用层实现的连接建立,消息到来,连接关闭,任意事件的回调函数
 * 2.自己实现了设置给accepter的描述符可对事件回调函数,完成新连接的建立,绑定对应的eventloop,完成各种回调函数的设置,启动非活跃连接超时销毁
 * 调用connection层的连接建立的回调函数,并且将连接信息保存到std::unordered_map<uint64_t, PtrConnection> _conns中
 * 3.void RemoveConnectionInLoop(const PtrConnection &conn)函数设置给了connection删除连接信息的回调函数,用户删除连接智能指针对象的
 * 最后一份引用计数
 * 4.提供添加定时器,设置线程数量等接口
 */
#pragma once

#include "connection.hpp"
#include "eventLoop.hpp"
#include "acceptor.hpp"
#include "loopThreadPool.hpp"

namespace hdp
{
    class TcpServer
    {
    private:
        uint64_t _next_id; // 这是一个自动增长的连接ID
        uint16_t _port;
        int _timeout;                                       // 这是非活跃连接的统计时间---多长时间无通信就是非活跃连接
        bool _enable_inactive_release;                      // 是否启动了非活跃连接超时销毁的判断标志
        EventLoop _baseloop;                                // 这是主线程的EventLoop对象，负责监听事件的处理
        Acceptor _acceptor;                                 // 这是监听套接字的管理对象
        LoopThreadPool _pool;                               // 这是从属EventLoop线程池
        std::unordered_map<uint64_t, PtrConnection> _conns; // 保存管理所有连接对应的shared_ptr对象

        using ConnectedCallback = std::function<void(const PtrConnection &)>;
        using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
        using ClosedCallback = std::function<void(const PtrConnection &)>;
        using AnyEventCallback = std::function<void(const PtrConnection &)>;
        using Functor = std::function<void()>;
        ConnectedCallback _connected_callback;
        MessageCallback _message_callback;
        ClosedCallback _closed_callback;
        AnyEventCallback _event_callback;

    private:
        // 添加定时任务
        void RunAfterInLoop(const Functor &task, int delay)
        {
            _next_id++;
            _baseloop.TimerAdd(_next_id, delay, task);
        }

        // 为新连接构造一个Connection进行管理
        void NewConnection(int fd, std::string &ip)
        {
            LOG_INFO("recv a new connection,ip: {}", ip);
            _next_id++;
            PtrConnection conn(new Connection(_pool.GetNextLoop(), _next_id, fd, ip));

            conn->SetConnectedCallback(_connected_callback);
            conn->SetClosedCallback(_closed_callback);
            conn->SetMessageCallback(_message_callback);
            conn->SetAnyEventedCallback(_event_callback);

            conn->SetSrvClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));

            // 启动非活跃连接释放
            if (_enable_inactive_release)
                conn->EnableInactiveRelease(_timeout);

            // 就绪初始化
            conn->Established();
            _conns.insert(std::make_pair(_next_id, conn));
        }

        void RemoveConnectionInLoop(const PtrConnection &conn)
        {
            int id = conn->Id();
            auto it = _conns.find(id);
            if (it != _conns.end())
            {
                _conns.erase(id);
            }
        }
        // 从管理Connection的_conns中移除连接信息
        void RemoveConnection(const PtrConnection &conn)
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
        }

    public:
        TcpServer(const uint16_t &port)
            : _next_id(0),
              _port(port),
              _enable_inactive_release(false),
              _acceptor(&_baseloop, port),
              _pool(&_baseloop)
        {
            // 设置监听套接字读事件的回调函数
            _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1, std::placeholders::_2));
            // 将监听套接字挂到baseloop上
            _acceptor.Listen();
        }

        // 设置线程数量
        void SetThreadCount(int count) { _pool.SetThreadCount(count); }

        void SetConnectedCallback(const ConnectedCallback &cb) { _connected_callback = cb; }
        void SetMessageCallback(const MessageCallback &cb) { _message_callback = cb; }
        void SetClosedCallback(const ClosedCallback &cb) { _closed_callback = cb; }
        void SetAnyEventCallback(const AnyEventCallback &cb) { _event_callback = cb; }

        // 启动非活跃连接销毁
        void EnableInactiveRelease(int timeout)
        {
            _enable_inactive_release = true;
            _timeout = timeout;
        }

        // 用于添加一个定时任务
        void RunAfter(const Functor &task, int delay)
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
        }

        // 启动服务器
        void Start()
        {
            // 线程池的创建
            _pool.Create();
            // 事件监控--》就绪事件处理--》执行任务
            _baseloop.Start();
        }
    };
}